#include "efflux.h"

void router(struct evhttp_request *r, void *arg) {
	const char *uri = evhttp_request_get_uri(r);

	char *static_file = (char *) malloc(strlen(LIBSRVR_HTDOCS) + strlen(uri) + strlen(LIBSRVR_INDEX) + 1);
	stpcpy(stpcpy(static_file, LIBSRVR_HTDOCS), uri);

	bool file_exists = true;
	struct stat st;
	if(stat(static_file, &st) == -1) {
		file_exists = false;
		evhttp_send_error(r, HTTP_NOTFOUND, "NOTFOUND");
	}
	else {
		if(S_ISDIR(st.st_mode)) {
			strcat(static_file, LIBSRVR_INDEX);

			if(stat(static_file, &st) == -1) {
				file_exists = false;
				evhttp_send_error(r, HTTP_NOTFOUND, "NOTFOUND");
			}
		}
	}

	if(file_exists) {
		int file_size = st.st_size;

		char *html;
		html = (char *) alloca(file_size);

		if(file_size != 0) {
			FILE *fp = fopen(static_file, "r");
			fread(html, 1, file_size, fp);
			fclose(fp);
		}
		
		// get MIME type
		char * mime_type;
		char * mime_header;

		mime_type = strrchr(static_file, '.'); 
		
		/* Text */
	    if ( strcmp(mime_type, ".txt") == 0 || strcmp(mime_type, ".h") == 0 || strcmp(mime_type, ".c") == 0 || strcmp(mime_type, ".cpp") == 0 ){
	        mime_header = "text/plain";
	    } else if ( strcmp( mime_type, ".css" ) == 0 ){
	        mime_header = "text/css";
	    } else if ( strcmp( mime_type, ".js" ) == 0 ){
	        mime_header = "text/javascript";
	    } else if ( strcmp(mime_type, ".xml") == 0 || strcmp(mime_type, ".xsl") == 0 ){
	        mime_header = "text/xml";
	    } else if ( strcmp(mime_type, ".xhtm") == 0 || strcmp(mime_type, ".xhtml") == 0 || strcmp(mime_type, ".xht") == 0 ){
	        mime_header = "application/xhtml+xml";
	    } else if ( strcmp(mime_type, ".html") == 0 || strcmp(mime_type, ".htm") == 0 || strcmp(mime_type, ".shtml") == 0 || strcmp(mime_type, ".hts") == 0 ){
	        mime_header = "text/html";

		/* Images */
	    } else if ( strcmp( mime_type, ".gif" ) == 0 ){
	        mime_header = "image/gif";
	    } else if ( strcmp( mime_type, ".png" ) == 0 ){
	        mime_header = "image/png";
	    } else if ( strcmp( mime_type, ".bmp" ) == 0 ){
	        mime_header = "application/x-MS-bmp";
	    } else if ( strcmp( mime_type, ".jpg" ) == 0 || strcmp( mime_type, ".jpeg" ) == 0 || strcmp( mime_type, ".jpe" ) == 0 || strcmp( mime_type, ".jpz" ) == 0 ){
	        mime_header = "image/jpeg";

		/* Audio & Video */
	    } else if ( strcmp( mime_type, ".wav" ) == 0 ){
	        mime_header = "audio/wav";
	    } else if ( strcmp( mime_type, ".wma" ) == 0 ){
	        mime_header = "audio/x-ms-wma";
	    } else if ( strcmp( mime_type, ".wmv" ) == 0 ){
	        mime_header = "audio/x-ms-wmv";
	    } else if ( strcmp( mime_type, ".au" ) == 0 || strcmp( mime_type, ".snd" ) == 0 ){
	        mime_header = "audio/basic";
	    } else if ( strcmp( mime_type, ".midi" ) == 0 || strcmp( mime_type, ".mid" ) == 0 ){
	        mime_header = "audio/midi";
	    } else if ( strcmp( mime_type, ".mp3" ) == 0 || strcmp( mime_type, ".mp2" ) == 0 ){
	        mime_header = "audio/x-mpeg";
		} else if ( strcmp( mime_type, ".rm" ) == 0  || strcmp( mime_type, ".rmvb" ) == 0 || strcmp( mime_type, ".rmm" ) == 0 ){
	        mime_header = "audio/x-pn-realaudio";
	    } else if ( strcmp( mime_type, ".avi" ) == 0 ){
	        mime_header = "video/x-msvideo";
	    } else if ( strcmp( mime_type, ".3gp" ) == 0 ){
	        mime_header = "video/3gpp";
	    } else if ( strcmp( mime_type, ".mov" ) == 0 ){
	        mime_header = "video/quicktime";
	    } else if ( strcmp( mime_type, ".wmx" ) == 0 ){
	        mime_header = "video/x-ms-wmx";
		} else if ( strcmp( mime_type, ".asf" ) == 0  || strcmp( mime_type, ".asx" ) == 0 ){
	        mime_header = "video/x-ms-asf";
	    } else if ( strcmp( mime_type, ".mp4" ) == 0 || strcmp( mime_type, ".mpg4" ) == 0 ){
	        mime_header = "video/mp4";
		} else if ( strcmp( mime_type, ".mpe" ) == 0  || strcmp( mime_type, ".mpeg" ) == 0 || strcmp( mime_type, ".mpg" ) == 0 || strcmp( mime_type, ".mpga" ) == 0 ){
	        mime_header = "video/mpeg";

		/* Documents */
	    } else if ( strcmp( mime_type, ".pdf" ) == 0 ){
	        mime_header = "application/pdf";
	    } else if ( strcmp( mime_type, ".rtf" ) == 0 ){
	        mime_header = "application/rtf";
		} else if ( strcmp( mime_type, ".doc" ) == 0  || strcmp( mime_type, ".mime_type" ) == 0 ){
	        mime_header = "application/msword";
		} else if ( strcmp( mime_type, ".xls" ) == 0  || strcmp( mime_type, ".xla" ) == 0 ){
	        mime_header = "application/msexcel";
		} else if ( strcmp( mime_type, ".hlp" ) == 0  || strcmp( mime_type, ".chm" ) == 0 ){
	        mime_header = "application/mshelp";
		} else if ( strcmp( mime_type, ".swf" ) == 0  || strcmp( mime_type, ".swfl" ) == 0 || strcmp( mime_type, ".cab" ) == 0 ){
	        mime_header = "application/x-shockwave-flash";
		} else if ( strcmp( mime_type, ".ppt" ) == 0  || strcmp( mime_type, ".ppz" ) == 0 || strcmp( mime_type, ".pps" ) == 0 || strcmp( mime_type, ".pot" ) == 0 ){
	        mime_header = "application/mspowerpoint";

		/* Binary & Packages */
	    } else if ( strcmp( mime_type, ".zip" ) == 0 ){
	        mime_header = "application/zip";
	    } else if ( strcmp( mime_type, ".rar" ) == 0 ){
	        mime_header = "application/x-rar-compressed";
	    } else if ( strcmp( mime_type, ".gz" ) == 0 ){
	        mime_header = "application/x-gzip";
	    } else if ( strcmp( mime_type, ".jar" ) == 0 ){
	        mime_header = "application/java-archive";
		} else if ( strcmp( mime_type, ".tgz" ) == 0  || strcmp( mime_type, ".tar" ) == 0 ){
	        mime_header = "application/x-tar";
		} else {
			mime_header = "application/octet-stream";
		}

		struct evbuffer *buffer;
		buffer = evbuffer_new();

		struct evkeyvalq *headers = evhttp_request_get_output_headers(r);
		//evhttp_add_header(headers, "Content-Type", "text/html; charset=UTF-8");
		//evhttp_add_header(headers, "Content-Type", "image/jpeg");
		

        char * c_size;
        itoa(file_size,c_size,10);
        evhttp_add_header(headers, "Server", LIBSRVR_SIGNATURE);
        evhttp_add_header(headers, "Accept-Ranges", "bytes");
        evhttp_add_header(headers, "Content-Length", c_size);
        evhttp_add_header(headers, "Content-Type", mime_header);

		evbuffer_add_reference(buffer,html,file_size,0,0);
		//evbuffer_add_printf(buffer, "%s", html);
		evhttp_send_reply(r, HTTP_OK, "OK", buffer);
		evbuffer_free(buffer);

		if(options.verbose) fprintf(stderr, "%s\t%d\n", static_file, file_size);
	}
	else {
		if(options.verbose) fprintf(stderr, "%s\t%s\n", static_file, "404 Not Found");
	}

	free(static_file);
}

int main(int argc, char **argv) {
	int opt;

	options.port = 8080;
	options.address = "0.0.0.0";
	options.verbose = 0;

	while((opt = getopt(argc,argv,"p:vh")) != -1) {
		switch(opt) {
			case 'p':
				options.port = atoi(optarg);
				break;
			case 'v':
				options.verbose = 1;
				break;
			case 'h':
				printf("Usage: ./efflux -p port -v[erbose] -h[elp]\n");
				exit(1);
		}
	}

	libbase = event_base_new();
	libsrvr = evhttp_new(libbase);
	evhttp_bind_socket(libsrvr, options.address, options.port);
	evhttp_set_gencb(libsrvr, router, NULL);
	event_base_dispatch(libbase);

	return 0;
}
